import {
  Body,
  Controller,
  Delete,
  Get,
  Header,
  Param,
  Post,
  Put,
} from '@nestjs/common';
import { IsString } from 'class-validator';
import {
  OmitType,
  PartialType,
  PickType,
  IntersectionType,
} from '@nestjs/mapped-types';
import { DbService } from 'src/common/db.service';
import { ObjectId } from 'mongodb';
import { omit } from 'lodash';
import * as Result from 'src/tool/result';

class Category {
  @IsString()
  _id: string;

  @IsString()
  name: string;

  @IsString({ each: true })
  type: string[];

  @IsString({ each: true })
  region: string[];
}

class CreateCategoryDto extends OmitType(Category, ['_id'] as const) {}

class UpdateCategoryDto extends IntersectionType(
  PartialType(PickType(Category, ['name', 'type', 'region'] as const)),
  PickType(Category, ['_id'] as const),
) {}

@Controller('category')
export class CategoryController {
  constructor(private readonly db_service: DbService) {}

  @Post()
  @Header('Content-type', 'application/json')
  async add(@Body() category: CreateCategoryDto) {
    const database = this.db_service.database;
    const collection = database.collection('category');
    const result = await collection.insertOne(category);
    return Result.success(Result.Code.ADD_SUCCESS, result).toJson();
  }

  @Delete(':id')
  @Header('Content-type', 'application/json')
  async remove(@Param('id') id: string) {
    const database = this.db_service.database;
    const collection = database.collection('category');
    const result = await collection.deleteOne({ _id: new ObjectId(id) });
    return Result.success(Result.Code.DELETE_SUCCESS, result).toJson();
  }

  @Put()
  @Header('Content-type', 'application/json')
  async update(@Body() category: UpdateCategoryDto) {
    const database = this.db_service.database;
    const collection = database.collection('category');
    const result = await collection.updateOne(
      { _id: new ObjectId(category._id) },
      { $set: omit(category, ['_id']) },
    );
    return Result.success(Result.Code.UPDATE_SUCCESS, result).toJson();
  }

  @Get()
  @Header('Content-type', 'application/json')
  async findAll() {
    const database = this.db_service.database;
    const collection = database.collection('category');
    const categorys = await collection.find({}).toArray();
    return Result.success(Result.Code.SELECT_SUCCESS, categorys).toJson();
  }
}
